{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "OHoSU6uI-xIt"
   },
   "outputs": [],
   "source": [
    "import random\n",
    "import gym\n",
    "import numpy as np\n",
    "import collections\n",
    "from tqdm import tqdm\n",
    "import torch\n",
    "import torch.nn.functional as F\n",
    "import matplotlib.pyplot as plt\n",
    "import rl_utils"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "TsptTKz6-xIv"
   },
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    ''' 经验回放池 '''\n",
    "    def __init__(self, capacity):\n",
    "        self.buffer = collections.deque(maxlen=capacity)  # 队列,先进先出\n",
    "\n",
    "    def add(self, state, action, reward, next_state, done):  # 将数据加入buffer\n",
    "        self.buffer.append((state, action, reward, next_state, done))\n",
    "\n",
    "    def sample(self, batch_size):  # 从buffer中采样数据,数量为batch_size\n",
    "        transitions = random.sample(self.buffer, batch_size)\n",
    "        state, action, reward, next_state, done = zip(*transitions)\n",
    "        return np.array(state), action, reward, np.array(next_state), done\n",
    "\n",
    "    def size(self):  # 目前buffer中数据的数量\n",
    "        return len(self.buffer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "_qO6koMR-xIw"
   },
   "outputs": [],
   "source": [
    "class Qnet(torch.nn.Module):\n",
    "    ''' 只有一层隐藏层的Q网络 '''\n",
    "    def __init__(self, state_dim, hidden_dim, action_dim):\n",
    "        super(Qnet, self).__init__()\n",
    "        self.fc1 = torch.nn.Linear(state_dim, hidden_dim)\n",
    "        self.fc2 = torch.nn.Linear(hidden_dim, action_dim)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.fc1(x))  # 隐藏层使用ReLU激活函数\n",
    "        return self.fc2(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wxZItCX4-xIw"
   },
   "outputs": [],
   "source": [
    "class DQN:\n",
    "    ''' DQN算法 '''\n",
    "    def __init__(self, state_dim, hidden_dim, action_dim, learning_rate, gamma,\n",
    "                 epsilon, target_update, device):\n",
    "        self.action_dim = action_dim\n",
    "        self.q_net = Qnet(state_dim, hidden_dim,\n",
    "                          self.action_dim).to(device)  # Q网络\n",
    "        # 目标网络\n",
    "        self.target_q_net = Qnet(state_dim, hidden_dim,\n",
    "                                 self.action_dim).to(device)\n",
    "        # 使用Adam优化器\n",
    "        self.optimizer = torch.optim.Adam(self.q_net.parameters(),\n",
    "                                          lr=learning_rate)\n",
    "        self.gamma = gamma  # 折扣因子\n",
    "        self.epsilon = epsilon  # epsilon-贪婪策略\n",
    "        self.target_update = target_update  # 目标网络更新频率\n",
    "        self.count = 0  # 计数器,记录更新次数\n",
    "        self.device = device\n",
    "\n",
    "    def take_action(self, state):  # epsilon-贪婪策略采取动作\n",
    "        if np.random.random() < self.epsilon:\n",
    "            action = np.random.randint(self.action_dim)\n",
    "        else:\n",
    "            state = torch.tensor([state], dtype=torch.float).to(self.device)\n",
    "            action = self.q_net(state).argmax().item()\n",
    "        return action\n",
    "\n",
    "    def update(self, transition_dict):\n",
    "        states = torch.tensor(transition_dict['states'],\n",
    "                              dtype=torch.float).to(self.device)\n",
    "        actions = torch.tensor(transition_dict['actions']).view(-1, 1).to(\n",
    "            self.device)\n",
    "        rewards = torch.tensor(transition_dict['rewards'],\n",
    "                               dtype=torch.float).view(-1, 1).to(self.device)\n",
    "        next_states = torch.tensor(transition_dict['next_states'],\n",
    "                                   dtype=torch.float).to(self.device)\n",
    "        dones = torch.tensor(transition_dict['dones'],\n",
    "                             dtype=torch.float).view(-1, 1).to(self.device)\n",
    "\n",
    "        q_values = self.q_net(states).gather(1, actions)  # Q值\n",
    "        # 下个状态的最大Q值\n",
    "        max_next_q_values = self.target_q_net(next_states).max(1)[0].view(\n",
    "            -1, 1)\n",
    "        q_targets = rewards + self.gamma * max_next_q_values * (1 - dones\n",
    "                                                                )  # TD误差目标\n",
    "        dqn_loss = torch.mean(F.mse_loss(q_values, q_targets))  # 均方误差损失函数\n",
    "        self.optimizer.zero_grad()  # PyTorch中默认梯度会累积,这里需要显式将梯度置为0\n",
    "        dqn_loss.backward()  # 反向传播更新参数\n",
    "        self.optimizer.step()\n",
    "\n",
    "        if self.count % self.target_update == 0:\n",
    "            self.target_q_net.load_state_dict(\n",
    "                self.q_net.state_dict())  # 更新目标网络\n",
    "        self.count += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 97226,
     "status": "ok",
     "timestamp": 1649955480772,
     "user": {
      "displayName": "Sam Lu",
      "userId": "15789059763790170725"
     },
     "user_tz": -480
    },
    "id": "acJ1letz-xIx",
    "outputId": "26487c0d-c504-44d6-eb15-5fb137b9488f"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Iteration 0:   0%|          | 0/50 [00:00<?, ?it/s]/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:21: UserWarning: Creating a tensor from a list of numpy.ndarrays is extremely slow. Please consider converting the list to a single numpy.ndarray with numpy.array() before converting to a tensor. (Triggered internally at  ../torch/csrc/utils/tensor_new.cpp:201.)\n",
      "Iteration 0: 100%|██████████| 50/50 [00:00<00:00, 364.64it/s, episode=50, return=9.300]\n",
      "Iteration 1: 100%|██████████| 50/50 [00:00<00:00, 59.58it/s, episode=100, return=12.300]\n",
      "Iteration 2: 100%|██████████| 50/50 [00:03<00:00, 13.81it/s, episode=150, return=123.000]\n",
      "Iteration 3: 100%|██████████| 50/50 [00:12<00:00,  4.02it/s, episode=200, return=160.200]\n",
      "Iteration 4: 100%|██████████| 50/50 [00:13<00:00,  3.67it/s, episode=250, return=200.000]\n",
      "Iteration 5: 100%|██████████| 50/50 [00:13<00:00,  3.64it/s, episode=300, return=192.900]\n",
      "Iteration 6: 100%|██████████| 50/50 [00:13<00:00,  3.73it/s, episode=350, return=194.300]\n",
      "Iteration 7: 100%|██████████| 50/50 [00:13<00:00,  3.64it/s, episode=400, return=199.900]\n",
      "Iteration 8: 100%|██████████| 50/50 [00:11<00:00,  4.42it/s, episode=450, return=198.000]\n",
      "Iteration 9: 100%|██████████| 50/50 [00:13<00:00,  3.58it/s, episode=500, return=200.000]\n"
     ]
    }
   ],
   "source": [
    "lr = 2e-3\n",
    "num_episodes = 500\n",
    "hidden_dim = 128\n",
    "gamma = 0.98\n",
    "epsilon = 0.01\n",
    "target_update = 10\n",
    "buffer_size = 10000\n",
    "minimal_size = 500\n",
    "batch_size = 64\n",
    "device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\n",
    "    \"cpu\")\n",
    "\n",
    "env_name = 'CartPole-v0'\n",
    "env = gym.make(env_name)\n",
    "random.seed(0)\n",
    "np.random.seed(0)\n",
    "env.seed(0)\n",
    "torch.manual_seed(0)\n",
    "replay_buffer = ReplayBuffer(buffer_size)\n",
    "state_dim = env.observation_space.shape[0]\n",
    "action_dim = env.action_space.n\n",
    "agent = DQN(state_dim, hidden_dim, action_dim, lr, gamma, epsilon,\n",
    "            target_update, device)\n",
    "\n",
    "return_list = []\n",
    "for i in range(10):\n",
    "    with tqdm(total=int(num_episodes / 10), desc='Iteration %d' % i) as pbar:\n",
    "        for i_episode in range(int(num_episodes / 10)):\n",
    "            episode_return = 0\n",
    "            state = env.reset()\n",
    "            done = False\n",
    "            while not done:\n",
    "                action = agent.take_action(state)\n",
    "                next_state, reward, done, _ = env.step(action)\n",
    "                replay_buffer.add(state, action, reward, next_state, done)\n",
    "                state = next_state\n",
    "                episode_return += reward\n",
    "                # 当buffer数据的数量超过一定值后,才进行Q网络训练\n",
    "                if replay_buffer.size() > minimal_size:\n",
    "                    b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size)\n",
    "                    transition_dict = {\n",
    "                        'states': b_s,\n",
    "                        'actions': b_a,\n",
    "                        'next_states': b_ns,\n",
    "                        'rewards': b_r,\n",
    "                        'dones': b_d\n",
    "                    }\n",
    "                    agent.update(transition_dict)\n",
    "            return_list.append(episode_return)\n",
    "            if (i_episode + 1) % 10 == 0:\n",
    "                pbar.set_postfix({\n",
    "                    'episode':\n",
    "                    '%d' % (num_episodes / 10 * i + i_episode + 1),\n",
    "                    'return':\n",
    "                    '%.3f' % np.mean(return_list[-10:])\n",
    "                })\n",
    "            pbar.update(1)\n",
    "\n",
    "# Iteration 0: 100%|██████████| 50/50 [00:00<00:00, 764.86it/s, episode=50,\n",
    "# return=9.300]\n",
    "# Iteration 1: 100%|██████████| 50/50 [00:04<00:00, 10.66it/s, episode=100,\n",
    "# return=12.300]\n",
    "# Iteration 2: 100%|██████████| 50/50 [00:24<00:00,  2.05it/s, episode=150,\n",
    "# return=123.000]\n",
    "# Iteration 3: 100%|██████████| 50/50 [01:25<00:00,  1.71s/it, episode=200,\n",
    "# return=153.600]\n",
    "# Iteration 4: 100%|██████████| 50/50 [01:30<00:00,  1.80s/it, episode=250,\n",
    "# return=180.500]\n",
    "# Iteration 5: 100%|██████████| 50/50 [01:24<00:00,  1.68s/it, episode=300,\n",
    "# return=185.000]\n",
    "# Iteration 6: 100%|██████████| 50/50 [01:32<00:00,  1.85s/it, episode=350,\n",
    "# return=193.900]\n",
    "# Iteration 7: 100%|██████████| 50/50 [01:31<00:00,  1.84s/it, episode=400,\n",
    "# return=196.600]\n",
    "# Iteration 8: 100%|██████████| 50/50 [01:33<00:00,  1.88s/it, episode=450,\n",
    "# return=193.800]\n",
    "# Iteration 9: 100%|██████████| 50/50 [01:34<00:00,  1.88s/it, episode=500,\n",
    "# return=200.000]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 573
    },
    "executionInfo": {
     "elapsed": 698,
     "status": "ok",
     "timestamp": 1649955495697,
     "user": {
      "displayName": "Sam Lu",
      "userId": "15789059763790170725"
     },
     "user_tz": -480
    },
    "id": "AFiCxG4W-xIy",
    "outputId": "b5610f6f-8df9-4156-ecb9-e8cb2901133c"
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "episodes_list = list(range(len(return_list)))\n",
    "plt.plot(episodes_list, return_list)\n",
    "plt.xlabel('Episodes')\n",
    "plt.ylabel('Returns')\n",
    "plt.title('DQN on {}'.format(env_name))\n",
    "plt.show()\n",
    "\n",
    "mv_return = rl_utils.moving_average(return_list, 9)\n",
    "plt.plot(episodes_list, mv_return)\n",
    "plt.xlabel('Episodes')\n",
    "plt.ylabel('Returns')\n",
    "plt.title('DQN on {}'.format(env_name))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "CDk1DgrL-xIz"
   },
   "outputs": [],
   "source": [
    "class ConvolutionalQnet(torch.nn.Module):\n",
    "    ''' 加入卷积层的Q网络 '''\n",
    "    def __init__(self, action_dim, in_channels=4):\n",
    "        super(ConvolutionalQnet, self).__init__()\n",
    "        self.conv1 = torch.nn.Conv2d(in_channels, 32, kernel_size=8, stride=4)\n",
    "        self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=4, stride=2)\n",
    "        self.conv3 = torch.nn.Conv2d(64, 64, kernel_size=3, stride=1)\n",
    "        self.fc4 = torch.nn.Linear(7 * 7 * 64, 512)\n",
    "        self.head = torch.nn.Linear(512, action_dim)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = x / 255\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = F.relu(self.conv3(x))\n",
    "        x = F.relu(self.fc4(x))\n",
    "        return self.head(x)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "第7章-DQN算法.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
